﻿using System;
using System.Web;
using System.Web.Mvc;
using SlamCms.Configuration;
using SlamCms.Data;
using SlamCms.Tracking;
using StackExchange.Profiling;

namespace SlamCms.Web
{
	public class SlamCmsHttpModule : IHttpModule
	{
		private static object _lock = new object();
		private static bool _startWasCalled = false;

		public void Dispose()
		{
		}

		public void Init(HttpApplication context)
		{
			context.BeginRequest += OnBeginRequest;
			context.EndRequest += OnEndRequest;
			context.Error += OnError;

			// Init is called once per HttpApplication instance so to execute code
			// once per AppDomain we use this lock
			lock (_lock)
			{
				if (!_startWasCalled)
				{
					_startWasCalled = true;
					this.OnStart(context);
				}
			}
		}

		private void OnStart(HttpApplication context)
		{
			Bootstrapper.Run(context);
		}

		private void OnBeginRequest(object sender, EventArgs e)
		{
			var httpContext = GetHttpContext(sender);
			if (IsProfilerEnabled(httpContext))
				MiniProfiler.Start();
		}

		private void OnEndRequest(object sender, EventArgs e)
		{
			var httpContext = GetHttpContext(sender);
			if (IsProfilerEnabled(httpContext))
				MiniProfiler.Stop();
		}

		private void OnError(object sender, EventArgs e)
		{
			if (ConfigurationHelpers.GetEnvironmentSetting(Constants.Settings.TrackingNotFoundsEnabled, true))
			{
				var httpContext = GetHttpContext(sender);
				var exception = httpContext.Server.GetLastError();
				var httpException = exception as HttpException;

				if (httpException != null && httpException.GetHttpCode() == 404)
					TrackNotFound(httpContext);
			}
		}

		private HttpContextBase GetHttpContext(object sender)
		{
			var httpApplication = sender as HttpApplication;
			return new HttpContextWrapper(httpApplication.Context);
		}

		private bool IsProfilerEnabled(HttpContextBase httpContext)
		{
			//TODO check cookie value security
			return httpContext.Request.Cookies[Constants.Cookies.Profiler] != null;
		}

		private void TrackNotFound(HttpContextBase httpContext)
		{
			var trackingService = DependencyResolver.Current.GetService<ITrackingService>();
			trackingService.TrackNotFound(httpContext.Request.RawUrl);
		}
	}
}
